﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Microsoft.VisualBasic.PowerPacks;
using VitCode.Castle.Entities;
using VitCode.WorkFlow.DataAccess;
using VitCode.WorkFlow.Entities;

namespace WorkFlowSettingApp
{
    public partial class ActivityCreator : Form
    {
        private const int EACH_WIDTH = 64;

        private Activity m_Activity;

        private WorkFlowAccess m_Access = new WorkFlowAccess();

        public ActivityCreator()
        {
            InitializeComponent();
        }

        public Guid KeyId { get; set; }

        protected void SetStartItem()
        {
            ucWorkItem.App_FlowId = 0;
            m_Access.BeginTransaction();
            try
            {
                var txtStartItem = new ucWorkItem();

                txtStartItem.Top = (Height - txtStartItem.Height) / 2;
                txtStartItem.ItemColor = SettingHelper.COLOR_START;
                txtStartItem.Text = "开始";
                txtStartItem.LevelNum = 1;
                txtStartItem.FlowId = ucWorkItem.App_FlowId;
                txtStartItem.Width = TEXTBOX_INIT_WIDTH;
                txtStartItem.OrderString = txtStartItem.CreateOrderString("", 1);

                WorkItem wi = new WorkItem();
                wi.Name = txtStartItem.Text;
                wi.Activity = m_Activity;
                wi.FixType = WorkItem.FIX_NEED;
                wi.Flag = WorkItem.FLAG_START;
                wi.LevelNum = 1;
                wi.OperateRole = ((Role)m_Access.GetSingleObjectByProVal(typeof(Role).Name, "Alias", "admin"));
                wi.Prams = "123";
                wi.TargetClassName = "123";
                wi.TargetUrl = "123";
                wi.OrderString = txtStartItem.OrderString;
                wi.FlowId = txtStartItem.FlowId;
                m_Access.Session.Save(wi);

                txtStartItem.WorkItem = wi;
                txtStartItem.Name = wi.Id.ToString();

                Controls.Add(txtStartItem);
                m_Access.Commit();
            }
            catch (Exception ex)
            {
                m_Access.RollBack();
                throw ex;
            }
            finally
            {
                m_Access.CloseSession();
            }
        }

        private LineShape GetLine(string strLineName)
        {
            LineShape line;
            
            var ctlLines = (from Shape c in shapeContainer1.Shapes where c.Name == strLineName select c).ToList();
            if (ctlLines.Count > 0 && ctlLines[0] is LineShape)
                line = ((LineShape)ctlLines[0]);
            else
                line = new LineShape { Name = strLineName };
            return line;
        }

        private void SetAtivityToForm(string acId)
        {
            if (!string.IsNullOrEmpty(acId))
            {
                IList items;
                IList relations;
                try
                {
                    items = m_Access.GetWorkItemsByActivityId(acId);
                    relations = m_Access.GetWorkItemRelationsByActivityId(acId);
                }
                finally
                {
                    m_Access.CloseSession();
                }
                var alLevels = new ArrayList();
                int objAmount = 0;
                foreach (WorkItem obj in items)
                {
                    objAmount++;
                    if (!alLevels.Contains(obj.LevelNum))
                    {
                        alLevels.Add(obj.LevelNum);
                    }
                    ucWorkItem ctlWorkItem;
                    var ctls = (from Control c in Controls where c.Name == obj.Id.ToString() select c).ToList();
                    if (ctls.Count > 0 && ctls[0] is ucWorkItem)
                        ctlWorkItem = ((ucWorkItem)ctls[0]);
                    else
                        ctlWorkItem = new ucWorkItem();
                    ctlWorkItem.Width = TEXTBOX_INIT_WIDTH;
                    ctlWorkItem.Text = obj.Name;
                    ctlWorkItem.LevelNum = obj.LevelNum;
                    ctlWorkItem.OrderString = obj.OrderString;
                    ctlWorkItem.FlowId = obj.FlowId;
                    ctlWorkItem.Name = obj.Id.ToString();
                    ctlWorkItem.WorkItem = obj;
                    foreach (WorkItemRelation rs in relations)
                    {
                        if (rs.ChildItem != rs.ParentItem)
                        {
                            if (objAmount == 1)
                            {

                                string strLineName = "line_" + rs.ChildItem.Id + "|" + rs.ParentItem.Id;
                                var line = GetLine(strLineName);
                                if (rs.ChildItem.LevelNum - rs.ParentItem.LevelNum > 1)
                                {
                                    var tempLine = GetLine("temp_" + strLineName);
                                    shapeContainer1.Shapes.Add(tempLine);
                                }
                                shapeContainer1.Shapes.Add(line);
                            }
                            if (rs.ChildItem.Id == obj.Id)
                            {
                                ctlWorkItem.ParentCtlNames += rs.ParentItem.Id + ";";
                            }
                            else if (rs.ParentItem.Id == obj.Id)
                            {
                                ctlWorkItem.ChildCtlNames += rs.ChildItem.Id + ";";
                            }
                        }
                    }
                    Controls.Add(ctlWorkItem);
                }
                SetControlsPosition();
            }
        }

        private void InitForm()
        {
            SettingHelper.IsKeyDownCtrl = false;
            if (KeyId == Guid.Empty)
            {
                if (m_Activity == null)
                {
                    txtActivityName.Focus();
                    txtActivityName.BackColor = Color.Yellow;
                }
                else
                    SetStartItem();
            }
            else
            {
                try
                {
                    var obj = m_Access.GetSingleObjectById(typeof(Activity).Name, KeyId.ToString());
                    if (obj != null && obj is Activity)
                    {
                        m_Activity = ((Activity)obj);
                    }
                }
                finally
                {
                    m_Access.CloseSession();
                }
                
            }
        }

        private void ActivityCreator_Load(object sender, EventArgs e)
        {
            InitForm();
        }

        private void SetLevelCtlsHeight(List<ucWorkItem> alWorkItem,int tempAmount)
        {
            if (alWorkItem.Count == 0)
                return;
            const int eachHeight = 40;

            var totelHeight = (alWorkItem.Count-1 + tempAmount) * eachHeight;
            var firstCtlTop = 10;
            if (totelHeight < Height)
            {
                firstCtlTop = (Height - totelHeight) / 2;
                for (int i = 0; i < alWorkItem.Count; i++)
                {
                    var c = (alWorkItem[i]);
                    c.Top = firstCtlTop + (i * eachHeight) - c.Height/2;
                }
            }
            else
            {
                for (int i = 0; i < alWorkItem.Count; i++)
                {
                    var c = (alWorkItem[i]);
                    c.Top = firstCtlTop + (i * eachHeight) - c.Height/2;
                }
            }
        }

        private void SetLines()
        {
            var lines =
                    (from LineShape o in shapeContainer1.Shapes where o.Name.StartsWith("line_") select o).
                        ToList();
            foreach(var line in lines)
            {
                if (line.Name.StartsWith("line_"))
                {
                    string[] ss = line.Name.Remove(0, 5).Split('|');
                    if (ss.Length == 2)
                    {
                        string parentCtlName = ss[1];
                        string childCtlName = ss[0];
                        var parentCtl = (from Control o in Controls where o.Name == parentCtlName select o).First();
                        var childCtl = (from Control o in Controls where o.Name == childCtlName select o).First();
                        if (parentCtl != null && childCtl != null)
                        {
                            int tempLong = 0;
                            int parentLvNum = ((ucWorkItem) parentCtl).LevelNum;
                            int childLvNum = ((ucWorkItem)childCtl).LevelNum;
                            int chaVal = childLvNum - parentLvNum;
                            if(chaVal>1)
                            {
                                var tempLine = (from LineShape o in shapeContainer1.Shapes where o.Name.StartsWith("temp_line_") select o).
                        First();
                                if (tempLine != null)
                                {
                                    tempLong = (chaVal - 1)*(EACH_WIDTH + TEXTBOX_INIT_WIDTH);
                                    tempLine.X1 = parentCtl.Left + parentCtl.Width;
                                    tempLine.Y1 = parentCtl.Top + (parentCtl.Height / 2);
                                    tempLine.X2 = tempLine.X1+tempLong;
                                    tempLine.Y2 = tempLine.Y1;
                                }
                            }
                            
                            line.X1 = parentCtl.Left + parentCtl.Width + tempLong;
                            line.Y1 = parentCtl.Top + (parentCtl.Height / 2);
                            line.X2 = childCtl.Left;
                            line.Y2 = childCtl.Top + (childCtl.Height / 2);
                        }
                    }
                }
            }
        }

        private bool IsOtherPevLvCtl(ucWorkItem ctl)
        {
            if (String.IsNullOrEmpty(ctl.ChildCtlNames))
                return true;
            else
            {
                foreach (Control c in Controls)
                {
                    if(ctl.ChildCtlNames.IndexOf(c.Name)>-1 && c is ucWorkItem )
                    {
                        var uc = ((ucWorkItem) c);
                        if (uc.LevelNum - ctl.LevelNum > 1)
                            return true;
                    }
                }
            }
            return false;
        }

        private void SetControlsPosition()
        {
            var ctls = (from Control o in Controls where o is ucWorkItem select o).ToList();
            if(ctls.Count < 2)
                return;
            var items = (from ucWorkItem o in ctls orderby o.LevelNum,o.OrderString select o).ToList();

            var alWorkItem = new List<ucWorkItem>();
            int tempLvNum = 1;
            

            for (var i = 0; i < items.Count;i++ )
            {
                var item = items[i];
                var lvNum = item.LevelNum;
                item.Left = (item.LevelNum - 1) * (TEXTBOX_INIT_WIDTH + EACH_WIDTH);

                if (tempLvNum != lvNum)
                {
                    var tempCtlsNull = (from ucWorkItem o in items
                                        where o.LevelNum < alWorkItem[0].LevelNum && IsOtherPevLvCtl(o)
                                        orderby o.LevelNum , o.OrderString
                                        select o).ToList();
                    alWorkItem.AddRange(tempCtlsNull);
                    SetLevelCtlsHeight(alWorkItem, 0);
                    tempLvNum = items[i].LevelNum;
                    alWorkItem.Clear();
                }
                alWorkItem.Add(items[i]);
                if(items.Count-1==i)
                {
                    SetLevelCtlsHeight(alWorkItem, 0);
                }
            }
            SetLines();
        }

        private const int TEXTBOX_INIT_WIDTH = 80;

        public void CreateWorkItem()
        {
            if (String.IsNullOrEmpty(SettingHelper.SelectCtlNames))
            {
                MessageBox.Show("请先选择WorkItem");
                return;
            }
            string strSelectCtlNames = SettingHelper.SelectCtlNames;
            
            if (strSelectCtlNames.IndexOf(",")>-1)
            {
                var ctls =
                    (from Control c in Controls where strSelectCtlNames.IndexOf(c.Name + ",") > -1 select c).ToList();
                var query = (from ucWorkItem c in ctls orderby c.LevelNum descending , c.OrderString select c);
                var ucParents = query.ToList();
                if (ucParents.Count > 0)
                {
                    m_Access.BeginTransaction();
                    try
                    {
                        var uc = new ucWorkItem();
                        var parentCtl = (ucParents[0]);
                        uc.ParentCtlNames = SettingHelper.SelectCtlNames;
                        uc.LevelNum = parentCtl.LevelNum + 1;
                        uc.Text = uc.LevelNum + "_" + uc.FlowId;
                        uc.Width = TEXTBOX_INIT_WIDTH;
                        uc.OrderString = uc.CreateOrderString(parentCtl.OrderString, uc.LevelNum);

                        WorkItem wi = new WorkItem();

                        wi.LevelNum = uc.LevelNum;
                        wi.Flag = WorkItem.FLAG_DOING;
                        wi.FixType = WorkItem.FIX_NEED;
                        wi.Activity = m_Activity;
                        wi.Name = uc.Text;
                        wi.OperateRole = parentCtl.WorkItem.OperateRole;
                        wi.Prams = "aaa" + uc.FlowId;
                        wi.TargetClassName = "TargetClassName" + uc.FlowId;
                        wi.TargetUrl = "TargetUrl" + uc.FlowId;
                        wi.OrderString = uc.OrderString;
                        wi.FlowId = uc.FlowId;

                        m_Access.SaveOrUpdate(wi);

                        uc.WorkItem = wi;
                        uc.Name = wi.Id.ToString();

                        foreach (ucWorkItem c in ucParents)
                        {
                            c.ChildCtlNames += uc.Name + ";";
                        }

                        foreach (ucWorkItem parent in ucParents)
                        {
                            var line = new LineShape();
                            line.Name = "line_" + uc.Name+ "|" + parent.Name;
                            var wir = new WorkItemRelation();
                            wir.ParentItem = parent.WorkItem;
                            wir.ChildItem = uc.WorkItem;
                            if(uc.WorkItem.LevelNum - parent.WorkItem.LevelNum > 1)
                            {
                                var templine = new LineShape();
                                templine.Name = "temp_"+line.Name;
                                shapeContainer1.Shapes.Add(templine);
                            }
                            m_Access.SaveOrUpdate(wir);
                            shapeContainer1.Shapes.Add(line);
                        }
                        Controls.Add(uc);
                        m_Access.Commit();
                    }
                    catch (Exception ex)
                    {
                        m_Access.RollBack();
                        throw ex;
                    }
                    finally
                    {
                        m_Access.CloseSession();
                    }
                }
                SetControlsPosition();
            }
        }

        private void ActivityCreator_KeyDown(object sender, KeyEventArgs e)
        {
            SettingHelper.IsKeyDownCtrl = true;
        }

        private void ActivityCreator_KeyUp(object sender, KeyEventArgs e)
        {
            SettingHelper.IsKeyDownCtrl = false;
        }

        private void btnSaveActivity_Click(object sender, EventArgs e)
        {
            m_Access.BeginTransaction();
            if (txtActivityName.Text.Length == 0)
            {
                txtActivityName.BackColor = Color.Yellow;
                txtActivityName.Focus();
                MessageBox.Show("活动名称不能为空");
                return;
            }

            m_Activity = new Activity();
            m_Activity.CreateTime = DateTime.Now;
            m_Activity.IsUsed = true;
            m_Activity.Name = txtActivityName.Text;

            try
            {
                m_Access.Session.Save(m_Activity);
                m_Access.Commit();
            }
            catch (Exception ex)
            {
                m_Access.RollBack();
                throw ex;
            }
            finally
            {
                m_Access.CloseSession();
            }
            SetStartItem();
        }

        private void ActivityCreator_Activated(object sender, EventArgs e)
        {
            if(m_Activity!=null)
                SetAtivityToForm(m_Activity.Id.ToString());
        }
    }
}